package com.lemon.boot.common.handler;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import com.lemon.boot.common.consts.RedisKeyConst;
import com.lemon.boot.common.properties.RememberMeConfigProperties;
import com.lemon.boot.common.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.web.authentication.rememberme.PersistentRememberMeToken;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author 李猛
 * @datetime 2024/8/1 15:48
 * @description 持久化记住我token
 */
@Slf4j
public class RedisTokenRepositoryHandler implements PersistentTokenRepository {
    public RedisService redisService;
    public RememberMeConfigProperties rememberMeConfigProperties;

    public RedisTokenRepositoryHandler(RedisService redisService, RememberMeConfigProperties rememberMeConfigProperties) {
        this.redisService = redisService;
        this.rememberMeConfigProperties = rememberMeConfigProperties;
    }

    /**
     * 创建token
     *
     * @param token
     */
    @Override
    public void createNewToken(PersistentRememberMeToken token) {
        log.info("RedisTokenRepositoryHandler.createNewToken,username:{},series:{},tokenValue:{},date:{}", token.getUsername(), token.getSeries(), token.getTokenValue(), DateUtil.format(token.getDate(), "yyyy-MM-dd HH:mm:ss"));
        String key = String.format("%s%s", RedisKeyConst.REDIS_KEY_REMEMBER_ME_SERIES, token.getSeries());
        boolean has = redisService.has(key);
        if (has) {
            redisService.del(key);
        }
        //过期时间
        long validity = rememberMeConfigProperties.getTokenValiditySeconds();
        redisService.save(key, token, validity, TimeUnit.SECONDS);
    }

    /**
     * 更新token
     *
     * @param series
     * @param tokenValue
     * @param lastUsed
     */
    @Override
    public void updateToken(String series, String tokenValue, Date lastUsed) {
        log.info("RedisTokenRepositoryHandler.updateToken:series:{},tokenValue:{},date:{}", series, tokenValue, DateUtil.format(lastUsed, "yyyy-MM-dd HH:mm:ss"));
        //1.key
        String key = String.format("%s%s", RedisKeyConst.REDIS_KEY_REMEMBER_ME_SERIES, series);
        //2.获取token
        JSONObject json = redisService.get(key, JSONObject.class);
        //3.新的token
        PersistentRememberMeToken newToken = new PersistentRememberMeToken(json.getStr("username"), series, tokenValue, new Date());
        //4.删除旧token
        redisService.del(key);
        redisService.save(key, newToken, rememberMeConfigProperties.getTokenValiditySeconds(), TimeUnit.SECONDS);
    }

    /**
     * 根据seriesId获取token
     *
     * @param seriesId
     * @return
     */
    @Override
    public PersistentRememberMeToken getTokenForSeries(String seriesId) {
        log.info("RedisTokenRepositoryHandler.getTokenForSeries:seriesId:{}", seriesId);
        String key = String.format("%s%s", RedisKeyConst.REDIS_KEY_REMEMBER_ME_SERIES, seriesId);
        //1.判断key是否存在
        boolean has = redisService.has(key);
        if (has) {
            JSONObject json = redisService.get(key, JSONObject.class);
            return new PersistentRememberMeToken(json.get("username").toString(), seriesId, json.get("tokenValue").toString(), new Date());
        }
        return null;
    }

    /**
     * 删除token
     *
     * @param username
     */
    @Override
    public void removeUserTokens(String username) {
        log.info("RedisTokenRepositoryHandler.removeUserTokens:username:{}", username);
        String keyStart = String.format("%s%s", RedisKeyConst.REDIS_KEY_REMEMBER_ME_SERIES, "*");
        Map<String, JSONObject> rememberMeTokenMap = redisService.keys(keyStart, JSONObject.class);
        //1.遍历map
        rememberMeTokenMap.forEach((k, v) -> {
            if (v.getStr("username").equals(username)) {
                redisService.del(k);
            }
        });
    }
}
